﻿using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Runtime.Versioning;
using System.Windows.Forms;
using Microsoft.Win32;

namespace zykControl
{
    /// <summary>
    /// Zyk风格的DataGridView
    /// </summary>
    public partial class ZykDataGrid
    {
        /// <summary>
        /// Zyk风格的DataGridView
        /// </summary>
        public ZykDataGrid()
        {
            InitializeComponent();
        }

        private bool mAutoCreateColumns = false;

        /// <summary>
        /// 是否自动创建列
        /// </summary>
        [Description("是否自动创建列")]
        public bool AutoCreateColumns
        {
            get
            {
                if (AutoGenerateColumns != mAutoCreateColumns)
                    AutoGenerateColumns = mAutoCreateColumns;
                return mAutoCreateColumns;
            }
            set
            {
                mAutoCreateColumns = value;
                AutoGenerateColumns = value;

            }
        }

        /// <summary>
        /// 按zyk风格重置若干属性的值
        /// </summary>
        [Description("按zyk风格重置若干属性的值")]
        public void SetZykStyle()
        {
            AutoGenerateColumns = false;
            ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
            ColumnHeadersHeight = 28;
            RowHeadersVisible = true;
            RowHeadersWidth = 25;
            MultiSelect = false;
            SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            ReadOnly = true;
            AllowUserToResizeRows = false;
            AllowUserToAddRows = false;
            AllowUserToDeleteRows = false;
            AllowUserToOrderColumns = true;
            BorderStyle = BorderStyle.Fixed3D;
            EnableHeadersVisualStyles = false;
        }

        /// <summary>
        /// 按zyk风格重置若干属性的值
        /// </summary>
        [Editor(typeof(ZykStyleEditor), typeof(UITypeEditor))]
        [Description("按zyk风格重置若干属性的值")]
        public object? ZykStyle { get; set; }

        /// <summary>
        /// ZykStyle编辑器
        /// </summary>
        public class ZykStyleEditor : UITypeEditor
        {
            /// <summary>
            /// ZykStyle编辑器的EditValue方法
            /// </summary>
            /// <param name="context"></param>
            /// <param name="provider"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public override object? EditValue(ITypeDescriptorContext? context, IServiceProvider provider, object? value)
            {
                return FrmZykStyleEditor.ShowA(context, provider, value) ? new object() : null;
            }

            /// <summary>
            /// ZykStyle编辑器的GetEditStyle方法
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext? context)
            {
                return UITypeEditorEditStyle.Modal;
            }
        }
        /// <summary>
        /// 完成了选择过程时发生
        /// </summary>
        /// <remarks></remarks>
        [Description("完成了选择过程时发生")]
        public event EventHandler? SelectFinish;

        /// <summary>
        /// 向上移动选定行
        /// </summary>
        /// <remarks></remarks>
        public void MoveUpSelect()
        {
            OnKeyDown(new KeyEventArgs(Keys.Up));
        }

        /// <summary>
        /// 向下移动选定行
        /// </summary>
        /// <remarks></remarks>
        public void MoveDownSelect()
        {
            OnKeyDown(new KeyEventArgs(Keys.Down));
        }

        /// <summary>
        /// 当前选中的单元格,如果没有选中则返回空引用
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public DataGridViewCell? SelectedCell
        {
            get
            {
                var dRow = SelectedRow;
                if (dRow is null) return null;
                for (int xx = 0, loopTo = dRow.Cells.Count - 1; xx <= loopTo; xx++)
                {
                    if (dRow.Cells[xx].Selected == true) return dRow.Cells[xx];
                }
                return null;
            }
        }

        private int mSelectedCellIndex = -1;
        /// <summary>
        /// 获取当前选中的单元格的列索引，如果没有选中列则返回-1
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public int SelectedCellIndex()
        {
            return mSelectedCellIndex;
        }

        /// <summary>
        /// 是否启用双缓冲
        /// </summary>
        public bool EnableDoubleBuffered
        {
            get
            {
                return DoubleBuffered;
            }
            set
            {
                DoubleBuffered = value;
            }
        }

        /// <summary>
        /// 当前选中的行,如果没有选中则返回空引用
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Description("当前选中的行,如果没有选中则返回空引用")]
        public DataGridViewRow? SelectedRow
        {
            get
            {
                // If Me.SelectedCell Is Nothing Then Return Nothing Else Return Me.Rows(Me.SelectedCell.RowIndex)
                if (SelectedRows.Count > 0)
                    return SelectedRows[0];
                else if (Rows.Count > 0)
                    return Rows[0];
                else
                    return null;
            }
        }

        //public DataGridViewCell get_SelectedCell(DataGridViewColumn theColumn)
        //{
        //    if (SelectedRow is null) return null;
        //    return SelectedRow.Cells[theColumn.Index];
        //}

        /// <summary>
        /// 定位到指定行号的行,成功时返回True
        /// </summary>
        /// <param name="theRowIndex"></param>
        /// <returns></returns>
        public bool SelectIndex(int theRowIndex)
        {
            if (theRowIndex < 0 | theRowIndex > RowCount - 1)
                return false;
            var dCell = FirstDisplayedCell;
            if (dCell is null)
                return false;
            Rows[theRowIndex].Selected = true;
            Rows[theRowIndex].Cells[dCell.ColumnIndex].Selected = true;
            return true;
        }

        // ''' <summary>
        // ''' 定位到使用了此DataRow的数据行上,并返回定位到的行号
        // ''' </summary>
        // ''' <param name="theRow"></param>
        // ''' <returns></returns>
        // Function SelectRow(theRow As DataRow) As Integer
        // Dim dCell = SelectedCell
        // For xx = 0 To Rows.Count - 1
        // Dim dRowView = Rows(xx).DataBoundItem
        // If TypeOf dRowView Is DataRowView Then
        // If DirectCast(dRowView, DataRowView).Row Is theRow Then
        // Rows(xx).Selected = True
        // If dCell IsNot Nothing Then Rows(xx).Cells(dCell.ColumnIndex).Selected = True
        // Return xx
        // End If
        // Else
        // Return -1
        // End If
        // Next
        // Return -1
        // End Function

        /// <summary>
        /// 当选中了任何内容时,返回True
        /// </summary>
        [Description("当选中了任何内容时,返回True")]
        public bool Selected
        {
            get
            {
                return CurrentRow is not null;
            }
        }

        /// <summary>
        /// 触发SelectFinish事件,但是只有在符合条件时事件才被触发
        /// </summary>
        /// <remarks></remarks>
        public void DoSelectFinish()
        {
            if (Selected == false) return;
            SelectFinish?.Invoke(this, new EventArgs());
        }

        //public void SelectFind(DataGridViewColumn theColumn, string FindText)
        //{
        //    int dSelIndex = theColumn.Index;
        //    if (theColumn.Visible == false) dSelIndex = GetDisplayColIndex();
        //    for (int xx = 0, loopTo = Rows.Count - 1; xx <= loopTo; xx++)
        //    {
        //        if ((Conversions.ToString(Rows[xx].Cells[theColumn.Index].Value) ?? "") == (FindText ?? ""))
        //        {
        //            Rows[xx].Cells[dSelIndex].Selected = true;
        //            Rows[xx].Selected = true;
        //            return;
        //        }
        //    }
        //}

        /// <summary>
        /// 选中找到的第一行
        /// </summary>
        /// <param name="theFunction"></param>
        public void SelectFind(Func<DataGridViewRow, bool> theFunction)
        {
            var dCell = SelectedCell;
            foreach (DataGridViewRow dRowView in Rows)
            {
                if (theFunction(dRowView))
                {
                    dRowView.Selected = true;
                    if (dCell is not null) dRowView.Cells[dCell.ColumnIndex].Selected = true;
                    return;
                }
            }
        }

        /// <summary>
        /// 返回从左计算的第一个可见列的列索引,如果没有任何可见列,返回-1
        /// </summary>
        /// <returns></returns>
        public int GetDisplayColIndex()
        {
            for (int xx = 0, loopTo = Columns.Count - 1; xx <= loopTo; xx++)
            {
                if (Columns[xx].Visible == true) return xx;
            }

            return -1;
        }

        private string mMainKey = "";
        private string mModule = "";

        /// <summary>
        /// 载入列的宽度布局
        /// </summary>
        /// <remarks></remarks>
        [SupportedOSPlatform("windows")]
        public void LoadLayout(string theKeyMain, string theModule = "")
        {
            mMainKey = theKeyMain;
            mModule = theModule;
            if (DesignMode == true) return;
            if (string.IsNullOrEmpty(mMainKey) || mMainKey is null) return;
            if (FindForm() is null || string.IsNullOrEmpty(FindForm()!.Name)) return;
            if (Name is null || string.IsNullOrEmpty(Name)) return;

            var dKey = Registry.CurrentUser.CreateSubKey("Software").CreateSubKey(mMainKey).CreateSubKey(FindForm()!.Name + (string.IsNullOrEmpty(theModule) ? "" : "_" + theModule)).CreateSubKey(Name);
            for (int xx = 0; xx < Columns.Count; xx++)
            {
                var aa = dKey.GetValue(xx.ToString())?.ToString();
                if (aa is null || string.IsNullOrEmpty(aa)) continue;
                if (!int.TryParse(aa, out var aaint)) continue;

                Columns[xx].Width = aaint;
            }

            dKey.Close();
        }

        /// <summary>
        /// 保存当前的列宽度布局
        /// </summary>
        /// <remarks></remarks>
        [SupportedOSPlatform("windows")]
        public void SaveLayout()
        {
            if (DesignMode == true)
                return;
            if (string.IsNullOrEmpty(mMainKey) || mMainKey is null)
                return;
            if (FindForm() is null || string.IsNullOrEmpty(FindForm()!.Name))
                return;
            if (Name is null || string.IsNullOrEmpty(Name))
                return;
            var dKey = Registry.CurrentUser.CreateSubKey("Software").CreateSubKey(mMainKey).CreateSubKey(FindForm()!.Name + (string.IsNullOrEmpty(mModule) ? "" : "_" + mModule)).CreateSubKey(Name);
            for (int xx = 0, loopTo = Columns.Count - 1; xx <= loopTo; xx++)
                dKey.SetValue(xx.ToString(), Columns[xx].Width.ToString());
            dKey.Close();
        }

        private void ZykDataGrid_CurrentCellChanged(object sender, EventArgs e)
        {
            if (CurrentCell is null)
            {
                mSelectedCellIndex = -1;
                return;
            }

            mSelectedCellIndex = CurrentCell.ColumnIndex;
        }

        /// <summary>
        /// 当按下Enter键时,是否用Tab键的功能代替它
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(false)]
        [Description("当按下Enter键时,是否用Tab键的功能代替它")]
        public bool KeyEnterConvertTab { get; set; } = false;
        /// <summary>
        /// 当此值为True时,回车只会跳转到允许编辑的单元格上(开通KeyEnterConvertTab之后才有效)
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(false)]
        [Description("当此值为True时,回车只会跳转到允许编辑的单元格上 ( 开通KeyEnterConvertTab之后才有效 )")]
        public bool KeyEnterConvertInKeyModeCell { get; set; } = false;
        /// <summary>
        /// 当此值为True时,回车永远不会跳转到下一行(开通KeyEnterConvertTab之后才有效)
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(false)]
        [Description("当此值为True时,回车永远不会跳转到下一行 ( 开通KeyEnterConvertTab之后才有效 )")]
        public bool KeyEnterConvertRowCurrentOnly { get; set; } = false;
        /// <summary>
        /// 当此值为True时,回车将被转换成F15
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(false)]
        [Description("当此值为True时,回车将被转换回F15 ( 开通此项后,KeyEnterConvertTab及相关属性都将失效 )")]
        public bool KeyEnterConvertF15 { get; set; } = false;

        /// <summary>
        /// 重写 ProcessCmdKey 方法
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if ((keyData & Keys.KeyCode) != Keys.Enter || !KeyEnterConvertF15 && !KeyEnterConvertTab) return base.ProcessCmdKey(ref msg, keyData);

            if (KeyEnterConvertF15)
            {
                SendKeys.Send("{F15}");
                return true;
            }
            if (!KeyEnterConvertTab)
            {
                return true;
            }
            if (Selected == false)
            {
                FindForm()!.SelectNextControl(this, true, true, true, true);
                return true;
            }

            int dSelectedRowIndex = -1;
            if (SelectedCell is not null) dSelectedRowIndex = SelectedCell.RowIndex;
            if (KeyEnterConvertInKeyModeCell)
            {
                if ((keyData & Keys.Shift) == Keys.Shift)
                {
                    // 后退
                    if (SelectedCell is null) return true;

                    int dSelectCol = -1;
                    int dCol = SelectedCellIndex();
                    for (int xx = dCol - 1; xx >= 0; xx -= 1)
                    {
                        if (Columns[xx].ReadOnly)
                            continue;
                        dSelectCol = xx;
                        break;
                    }

                    if (dSelectCol == -1)
                    {
                        if (KeyEnterConvertRowCurrentOnly || dSelectedRowIndex == 0)
                        {
                            FindForm()!.SelectNextControl(this, false, true, true, true);
                        }
                        else
                        {
                            dSelectCol = -1;
                            for (int xx = Columns.Count - 1; xx >= 0; xx -= 1)
                            {
                                if (Columns[xx].ReadOnly)
                                    continue;
                                dSelectCol = xx;
                                break;
                            }

                            if (dSelectCol < 0)
                                dSelectCol = Columns.Count - 1;
                            if (dSelectCol < 0)
                                return true;
                            Rows[dSelectedRowIndex - 1].Cells[dSelectCol].Selected = true;
                        }
                    }
                    else if (SelectedRow != null)
                    {
                        SelectedRow.Cells[dSelectCol].Selected = true;
                    }
                }
                else
                {
                    // 前进
                    if (SelectedCell is null)
                        return true;
                    int dSelectCol = -1;
                    int dCol = SelectedCellIndex();
                    for (int xx = dCol + 1, loopTo = Columns.Count - 1; xx <= loopTo; xx++)
                    {
                        if (Columns[xx].ReadOnly)
                            continue;
                        dSelectCol = xx;
                        break;
                    }

                    if (dSelectCol == -1)
                    {
                        if (KeyEnterConvertRowCurrentOnly || dSelectedRowIndex >= Rows.Count - 1)
                        {
                            FindForm()!.SelectNextControl(this, true, true, true, true);
                        }
                        else
                        {
                            dSelectCol = -1;
                            for (int xx = 0, loopTo1 = Columns.Count - 1; xx <= loopTo1; xx++)
                            {
                                if (Columns[xx].ReadOnly)
                                    continue;
                                dSelectCol = xx;
                                break;
                            }

                            if (dSelectCol < 0)
                                return true;
                            Rows[dSelectedRowIndex + 1].Cells[dSelectCol].Selected = true;
                        }
                    }
                    else if (SelectedRow != null)
                    {
                        SelectedRow.Cells[dSelectCol].Selected = true;
                    }
                }
            }
            else
            {
                SendKeys.Send("\t");
            }

            return true;
        }

        private void ZykDataGrid_EditingControlShowing(object? sender, DataGridViewEditingControlShowingEventArgs e)
        {
            e.Control.TextChanged -= DataGridCellTextChanged;
            e.Control.KeyDown -= DataGirdCellKeyDown;
            e.Control.KeyPress -= DataGridCellKeyPress;
            e.Control.TextChanged += DataGridCellTextChanged;
            e.Control.KeyDown += DataGirdCellKeyDown;
            e.Control.KeyPress += DataGridCellKeyPress;
        }

        /// <summary>
        /// 当被编辑的单元格的内容发生改变时被触发
        /// </summary>
        public event EventHandler? CellTextChanged;

        /// <summary>
        /// 当被编辑的单元格内有键按下时被触发
        /// </summary>
        public event KeyEventHandler? CellKeyDown;

        /// <summary>
        /// 当被编辑的单元格内有字符产生时被触发
        /// </summary>
        public event KeyPressEventHandler? CellKeyPress;

        private void DataGridCellTextChanged(object? sender, EventArgs e)
        {
            CellTextChanged?.Invoke(sender, e);
        }

        private void DataGridCellKeyPress(object? sender, KeyPressEventArgs e)
        {
            CellKeyPress?.Invoke(sender, e);
        }

        private void DataGirdCellKeyDown(object? sender, KeyEventArgs e)
        {
            CellKeyDown?.Invoke(sender, e);
        }

        private void ZykDataGrid_RowStateChanged(object? sender, DataGridViewRowStateChangedEventArgs e)
        {
            if (sender is not DataGridView dgv) return;
            var row = e.Row;
            // 只处理链接列和选中状态变化
            if (row.Selected && (e.StateChanged == DataGridViewElementStates.Selected))
            {
                foreach (DataGridViewColumn col in dgv.Columns)
                {
                    if (col is DataGridViewLinkColumn column && row.Cells[column.Index] is DataGridViewLinkCell linkCell)
                    {
                        // 选中时的样式
                        linkCell.LinkColor = column.LinkColor;
                        linkCell.ActiveLinkColor = column.ActiveLinkColor;
                        linkCell.VisitedLinkColor = column.VisitedLinkColor;
                        linkCell.Style.BackColor = column.DefaultCellStyle.SelectionBackColor;
                        linkCell.Style.ForeColor = column.DefaultCellStyle.SelectionForeColor;
                    }
                }
            }
        }
    }
}